package java_thinking.unit_21._21_3;

import java.util.HashSet;
import java.util.Set;

/**
 * @Desc:   3.2 发布与逸出
 * @author: cww
 * @DateTime: 2019/5/31 8:46
 */

public class PublishAndEscape {
    /**
     * 对外发布的对象
     */
    public static Set<Secret> knownSecrets;

    public void initialize() {
        knownSecrets = new HashSet<Secret>();
    }
}
class Secret {
}

/**
 * 任何调用者都能修改这个数组内容，数组 states 已经逸出了它所在的作用域，本应是私有的变量，却发布了
 */
class UnsafeStates {
    private String[] states = new String[]{
            "AK", "AL"
    };

    public String[] getStates() {
        return states;
    }
}

/**
 * 对外发布EventListener 时，隐式的发布了一个ThisEscape 实例   不要这么做
 */
class ThisEscape {
    /**
     * 特殊的逸出示例，this引用在构造函数中逸出，这种对象就被认为是不正确的构造
     * @param source
     */
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener() {
            @Override
            public void onEvent(Event e) {
                doSomething(e);
            }
        });
    }

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}

/**
 * 3-8 如果想在构造函数中注册一个事件监听器或者启动线程，那么可以使用一个私有的构造函数和一个
 *      公共的工厂方法，从而避免this在构造过程中逸出
 */
class SafeListener {
    private final EventListener listener;

    private SafeListener() {
        listener = new EventListener() {
            @Override
            public void onEvent(Event e) {
                doSomething(e);
            }
        };
    }

    public static SafeListener newInstance(EventSource source) {
        SafeListener safe = new SafeListener();
        source.registerListener(safe.listener);
        return safe;
    }

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}